package com.fjec.paid.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fjec.common.util.DateUtil;
import com.fjec.common.util.JsonUtil;
import com.fjec.common.util.SequenceIdGenerator;
import com.fjec.common.ys.PaidHelper;
import com.fjec.common.ys.YsProperties;
import com.fjec.paid.entity.BizDistributionDetail;
import com.fjec.paid.entity.BizOrderRefund;
import com.fjec.paid.entity.BizOrderRefundLog;
import com.fjec.paid.mapper.BizOrderRefundMapper;
import com.fjec.paid.service.IBizDistributionDetailService;
import com.fjec.paid.service.IBizOrderRefundLogService;
import com.fjec.paid.service.IBizOrderRefundService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 007.订单退款表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-11-09
 */
@Service
public class BizOrderRefundServiceImpl extends ServiceImpl<BizOrderRefundMapper, BizOrderRefund> implements IBizOrderRefundService {

    @Resource
    private BizOrderRefundMapper mapper;

    @Resource
    private IBizOrderRefundLogService bizOrderRefundLogService;

    @Resource
    private IBizDistributionDetailService bizDistributionDetailService;

    @Resource
    private PaidHelper paidHelper;

    @Autowired
    private SequenceIdGenerator idGenerator;

    @Autowired
    private YsProperties ysProperties;

    @Override
    public int saveRefund(Long id, Long orderId, Long subOrderId, String amount) {
        BizOrderRefund refund = new BizOrderRefund();
        refund.setOrderId(orderId);
        refund.setSubOrderId(subOrderId);
        refund.setComplaintId(id);
        refund.setPaymentType(1);
        refund.setPayment((int) (Double.parseDouble(amount) * 100));
        refund.setCreateTime(DateUtil.nowLdt());
        refund.setRefundStatus(1);
        refund.setSyncStatus(0);
        boolean saved = this.save(refund);
        if (saved)
            return 0;
        else
            return -1;
    }

    @Override
    public List<Map<String, Object>> getRefundInfo(int limit, int minutes) {
        return mapper.getRefundInfo(limit, minutes);
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void doRefund(Map<String, Object> refundInfo) {
        Long id = MapUtils.getLong(refundInfo, "id");
        String outTradeNo = MapUtils.getString(refundInfo, "outTradeNo");
        String shopDate = MapUtils.getString(refundInfo, "shopDate");
        String tradeNo = MapUtils.getString(refundInfo, "tradeNo");
        Integer totalAmount = MapUtils.getInteger(refundInfo, "totalAmount");
        Integer amount = MapUtils.getInteger(refundInfo, "refundAmount");
        String refundAmount = String.valueOf(amount.doubleValue() / 100);
        Long orderId = MapUtils.getLong(refundInfo, "orderId");
        // refund log表
        BizOrderRefundLog refundLog = new BizOrderRefundLog();
        refundLog.setRefundId(id);
        refundLog.setTradeNo(tradeNo);
        refundLog.setOutTradeNo(outTradeNo);
        refundLog.setOutRequestNo(String.valueOf(idGenerator.nextId()));
        refundLog.setTotalAmount(totalAmount);
        refundLog.setRefundAmount(amount);


        List<Map<String, Object>> orderDivList = new ArrayList<>();

        List<BizDistributionDetail> distributionDetails = bizDistributionDetailService
                .list(new QueryWrapper<BizDistributionDetail>().eq("OrderId", orderId));
        List<Map<String, Object>> refundSplitInfo = new ArrayList<>();
        distributionDetails.forEach(dd -> {
            // 构建分账明细
            Map<String, Object> div = new HashMap<>();
            div.put("division_mer_id", dd.getDivisionMerUsercode());
            div.put("division_ratio", dd.getDivRatio());
            String isChargeFee;
            if (dd.getIsChargeFee() == 1)
                isChargeFee = "01";
            else
                isChargeFee = "02";
            div.put("is_charge_fee", isChargeFee);
            orderDivList.add(div);

            // 构建退款明细
            if (!dd.getDivisionMerUsercode().equals(ysProperties.getSellerId())) {
                Map<String, Object> shopRefund = new HashMap<>();
                double refAmount = amount.doubleValue() / 100;
                shopRefund.put("refund_mer_id", dd.getDivisionMerUsercode());
                DecimalFormat df = new DecimalFormat("#.00");
                String str = df.format(dd.getDivRatio().multiply(new BigDecimal(refAmount)));
                double shopAmount = Double.parseDouble(str);
                shopRefund.put("refund_amount", shopAmount);
                if (shopAmount != 0)
                    refundSplitInfo.add(shopRefund);

                Map<String, Object> platformRefund = new HashMap<>();
                platformRefund.put("refund_mer_id", ysProperties.getSellerId());
                double platformAmount = Double.parseDouble(df.format(refAmount - shopAmount));
                platformRefund.put("refund_amount", platformAmount);
                if (platformAmount != 0)
                    refundSplitInfo.add(platformRefund);
            }



        });

        // 发起退款请求
        try {
            Map<String, Object> result = paidHelper.divideRefund(outTradeNo, shopDate, tradeNo, refundAmount, "商品品质问题退款",
                    refundLog.getOutRequestNo(), refundSplitInfo, orderDivList);

            Map<String, Object> bizResponse = MapUtils.getMap(result, "ysepay_online_trade_refund_split_response");
            // 落库返回报文
            refundLog.setYsResponse(JsonUtil.toJson(bizResponse));

            // 校验返回码
            String code = MapUtils.getString(bizResponse, "code");
            if (code.equals("10000")) {
                // 申请退款成功 落库成功结果
                refundLog.setRefundState(2);
                String accountDate = MapUtils.getString(bizResponse, "account_date");
                String realAmount = MapUtils.getString(bizResponse, "refund_amount");
                refundLog.setAccountDate(accountDate);
                refundLog.setRefundAmount((int) (Double.parseDouble(realAmount) * 100));
                refundLog.setYsResponse(JsonUtil.toJson(bizResponse));
                // 更新退款表 退款状态为退款中
                this.update(new UpdateWrapper<BizOrderRefund>().eq("Id", id).set("RefundStatus", 2));
            } else {
                // 申请退款失败
                refundLog.setRefundState(1);
                refundLog.setYsResponse(JsonUtil.toJson(bizResponse));
            }

        } catch (Exception e) {
            log.error(e.getMessage());
        }

        refundLog.setCreateTime(DateUtil.nowLdt());
        bizOrderRefundLogService.save(refundLog);
    }

    @Override
    public List<Map<String, Object>> getRefundings(int limit) {
        return mapper.getRefundings(limit);
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void doQuery(Map<String, Object> ref) {
        String tradeNo = MapUtils.getString(ref, "tradeNo");
        String outTradeNo = MapUtils.getString(ref, "outTradeNo");
        String outRequestNo = MapUtils.getString(ref, "outRequestNo");
        Long refundId = MapUtils.getLong(ref, "refundId");

        try {
            Map<String, Object> resMap = paidHelper.queryRefund(tradeNo, outTradeNo, outRequestNo);
            Map<String, Object> infoMap = MapUtils.getMap(resMap, "ysepay_online_trade_refund_query_response");
            String code = MapUtils.getString(infoMap, "code");
            String msg = MapUtils.getString(infoMap, "msg");
            String funds_state = MapUtils.getString(infoMap, "funds_state");
            if (code.equals("10000") && msg.equals("Success")) {
                if (funds_state.equals("success")) {
                    // 退款成功
                    // 退款表
                    this.update(new UpdateWrapper<BizOrderRefund>()
                                        .eq("Id", refundId)
                                        .eq("RefundStatus", 2)
                                        .set("RefundStatus", 4));
                    // 退款log表
                    bizOrderRefundLogService.update(new UpdateWrapper<BizOrderRefundLog>()
                            .eq("RefundId", refundId)
                            .eq("RefundState", 2)
                            .set("RefundState", 4));
                } else if (funds_state.equals("fail")) {
                    // 退款失败
                    this.update(new UpdateWrapper<BizOrderRefund>()
                            .eq("Id", refundId)
                            .eq("RefundStatus", 2)
                            .set("RefundStatus", 3));
                    bizOrderRefundLogService.update(new UpdateWrapper<BizOrderRefundLog>()
                            .eq("RefundId", refundId)
                            .eq("RefundState", 2)
                            .set("RefundState", 3));
                } else if (funds_state.equals("in_process")) {
                    // 退款处理中 无需更新退款状态, do nothing
                }
            } else {
                // 一般是请求参数错误
//                ACQ.SYSTEM_ERROR	系统错误	重新发起请求
//                ACQ.INVALID_PARAMETER	参数无效	检查请求参数，修改后重新发起请求
//                ACQ.TRADE_NOT_EXIST	查询退款的交易不存在	确认交易号是否为正确的支付宝交易号，修改后重新查询
            }

        } catch (Exception e) {
            // 网络异常等，do nothing
        }
    }
}
